/*
 * Copyright (c) 2018-2023 北京华恒盛世科技有限公司
 * QUICKPOOL is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *     http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
*/

#include "jm.h"
#include "lib.h"

/**
 * @brief       XDR: xdr function to exchange node information between
 *              master JM and slave JM.
 *
 * @param[in|out]   xdrs     #1: xdrs for exchanging data
 * @param[in|out]   info     #2: node information to be exchanged
 * @param[in]       hdr      #3: XDR header
 * @param[in|out]   argument #4: extra data
 *
 * @retval      TRUE         #1: succeed
 * @retval      FALSE        #2: failed, xdr size not enough or memory not enough
 *
 * @note        xdrs has 3 types.
 *              XDR_FREE, means to free the allocated memory.
 *              XDR_ENCODE, means to encode data into xdrs.
 *              XDR_DECODE, menas to decode data from xdrs.
 */
bool_t
jm_xdr_staticinfo(XDR *xdrs, void *info, struct header *hdr, void *arguments)
{
    struct hostNode *hostInfo = (struct hostNode *)info;
    struct staticInfo *sip = &(hostInfo->static_info);

    if (!(xdr_int(xdrs, &(sip->maxcpu)) && xdr_double(xdrs, &(sip->maxmem))
          && xdr_double(xdrs, &(sip->maxswap))
          && xdr_double(xdrs, &(sip->maxtmp)))) {

        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_int(maxcpu and so on)");
        return FALSE;
    }

    int numaFlag = 0; 
    if (XDR_ENCODE == xdrs->x_op && NULL != sip->numa) {
        numaFlag = 1;
    }
    
    if (!xdr_int(xdrs, &numaFlag)){
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(numaFlag)");
        return FALSE;
    }

    if (!(gf_xdr_string(xdrs, &sip->host_type, hdr, NULL)
          && gf_xdr_string(xdrs, &sip->host_arch, hdr, NULL))) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "gf_xdr_string(host_type and so on)");
        return FALSE;
    }

    if (!xdr_u_int(xdrs, &hostInfo->num_GPU)) {
        log_message(ERR, NOCLASS, STR_FUNC_FAIL, __func__, "xdr_u_int(num_GPU)");
        return FALSE;
    }

    if (XDR_DECODE == xdrs->x_op && 0 < hostInfo->num_GPU) {
        hostInfo->gpuinfo_static = (struct hostGPUList *)calloc(hostInfo->num_GPU,
                                                                sizeof(struct hostGPUList));
        hostInfo->gpuinfo_dynamic = (struct hostGPULoad *)calloc(hostInfo->num_GPU,
                                                                 sizeof(struct hostGPULoad));

        if (NULL == hostInfo->gpuinfo_static || NULL == hostInfo->gpuinfo_dynamic) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        hostInfo->num_GPU*(sizeof(struct hostGPUList)+sizeof(struct hostGPULoad)));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    unsigned int i;
    for (i = 0;  i < hostInfo->num_GPU; i++) {       
        if (!(xdr_int(xdrs, &(hostInfo->gpuinfo_static[i].gpu_id))
              && xdr_double(xdrs, &(hostInfo->gpuinfo_static[i].gpu_maxmem))
              && xdr_float(xdrs, &(hostInfo->gpuinfo_static[i].gpu_factor))
              && gf_xdr_string(xdrs, &(hostInfo->gpuinfo_static[i].gpu_model), hdr, NULL))) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__,
                        "xdr_int(gpuinfo_static)", i);
            return FALSE;
        }

        if (!(xdr_int(xdrs, &(hostInfo->gpuinfo_dynamic[i].gpu_id))
              && xdr_float(xdrs, &(hostInfo->gpuinfo_dynamic[i].gpu_ut))
              && xdr_double(xdrs, &(hostInfo->gpuinfo_dynamic[i].avail_gpu_mem))
              && xdr_int(xdrs, &(hostInfo->gpuinfo_dynamic[i].gpu_mode))
              && gf_xdr_string(xdrs, &(hostInfo->gpuinfo_dynamic[i].status), hdr, NULL)
              && xdr_u_int(xdrs, &(hostInfo->gpuinfo_dynamic[i].gpu_temperature))
              && gf_xdr_string(xdrs, &(hostInfo->gpuinfo_dynamic[i].error), hdr, NULL))) {

            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL, __func__,
                        "xdr_int(gpuinfo_dynamic)", i);
            return FALSE;
        }
    }

    if (0 < numaFlag && XDR_DECODE == xdrs->x_op) {

        sip->numa = (numa_obj_t *)calloc(1, sizeof(struct numa_obj));
        if (NULL == sip->numa) {
            log_message(ERR, NOCLASS, STR_FUNC_D_FAIL_M, __func__, "calloc",
                        sizeof(struct numa_obj));
            quickpool_errno = ERROR_MEMORY;
            return FALSE;
        }
    }

    if (0 < numaFlag && NULL != sip->numa) {
        if (!gf_xdr_element(xdrs, (void *)(sip->numa), hdr, xdr_numainfo, NULL)) {
            return FALSE;
        }
    }  

    return TRUE;
} // end function jm_xdr_staticinfo
